package jwt

import (
	"errors"
	"time"

	"github.com/golang-jwt/jwt/v5"
)

// Claims JWT声明结构
type Claims struct {
	UserID   uint   `json:"user_id"`
	Username string `json:"username"`
	jwt.RegisteredClaims
}

// Config JWT配置
type Config struct {
	Secret     string        // JWT密钥
	ExpireTime time.Duration // 过期时间
	Issuer     string        // 签发者
}

// Manager JWT管理器
type Manager struct {
	config *Config
}

// NewManager 创建JWT管理器
func NewManager(config *Config) *Manager {
	if config.ExpireTime == 0 {
		config.ExpireTime = 2 * time.Hour // 默认2小时
	}
	if config.Issuer == "" {
		config.Issuer = "x-admin"
	}
	return &Manager{
		config: config,
	}
}

// GenerateToken 生成JWT token
func (m *Manager) GenerateToken(userID uint, username string) (string, time.Time, error) {
	nowTime := time.Now()
	expireTime := nowTime.Add(m.config.ExpireTime)

	claims := Claims{
		UserID:   userID,
		Username: username,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(expireTime),
			IssuedAt:  jwt.NewNumericDate(nowTime),
			Issuer:    m.config.Issuer,
		},
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	tokenString, err := token.SignedString([]byte(m.config.Secret))
	if err != nil {
		return "", time.Time{}, err
	}

	return tokenString, expireTime, nil
}

// ParseToken 解析JWT token
func (m *Manager) ParseToken(tokenString string) (*Claims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		// 验证签名方法
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, errors.New("invalid signing method")
		}
		return []byte(m.config.Secret), nil
	})

	if err != nil {
		return nil, err
	}

	if claims, ok := token.Claims.(*Claims); ok && token.Valid {
		return claims, nil
	}

	return nil, jwt.ErrTokenMalformed
}

// ValidateToken 验证token是否有效
func (m *Manager) ValidateToken(tokenString string) bool {
	_, err := m.ParseToken(tokenString)
	return err == nil
}

// RefreshToken 刷新token（如果token在刷新窗口期内）
func (m *Manager) RefreshToken(tokenString string, refreshWindow time.Duration) (string, time.Time, error) {
	claims, err := m.ParseToken(tokenString)
	if err != nil {
		return "", time.Time{}, err
	}

	// 检查是否在刷新窗口期内
	if refreshWindow > 0 {
		timeUntilExpiry := time.Until(claims.ExpiresAt.Time)
		if timeUntilExpiry > refreshWindow {
			return "", time.Time{}, errors.New("token not in refresh window")
		}
	}

	// 生成新token
	return m.GenerateToken(claims.UserID, claims.Username)
}

// 全局默认管理器
var defaultManager *Manager

// InitDefault 初始化默认JWT管理器
func InitDefault(secret string) {
	defaultManager = NewManager(&Config{
		Secret:     secret,
		ExpireTime: 2 * time.Hour,
		Issuer:     "x-admin",
	})
}

// GenerateToken 使用默认管理器生成token
func GenerateToken(userID uint, username string) (string, time.Time, error) {
	if defaultManager == nil {
		return "", time.Time{}, errors.New("JWT manager not initialized")
	}
	return defaultManager.GenerateToken(userID, username)
}

// ParseToken 使用默认管理器解析token
func ParseToken(tokenString string) (*Claims, error) {
	if defaultManager == nil {
		return nil, errors.New("JWT manager not initialized")
	}
	return defaultManager.ParseToken(tokenString)
}

// ValidateToken 使用默认管理器验证token
func ValidateToken(tokenString string) bool {
	if defaultManager == nil {
		return false
	}
	return defaultManager.ValidateToken(tokenString)
}
